﻿using System;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using System.Collections.ObjectModel;
using System.Linq;


namespace G.Reader.ViewModel
{
    public class MessageViewModel : NotifyObject
    {
        private static MessageViewModel instance;
        public static MessageViewModel Instance
        {
            get
            {
                return instance;
            }
        }

        private ObservableCollection<UserInfoService.UserInfo> friends;
        public ObservableCollection<UserInfoService.UserInfo> Friends
        {
            get
            {
                return friends;
            }
            set
            {
                if (!object.ReferenceEquals(value, friends))
                {
                    friends = value;
                    this.NotifyPropertyChanged("Friends");
                }
            }
        }

        private UserInfoService.UserInfo selectedUserInfo;
        public UserInfoService.UserInfo SelectedUserInfo
        {
            get
            {
                return selectedUserInfo;
            }
            set
            {
                //if (!object.ReferenceEquals(value, selectedUserInfo))
                //{
                selectedUserInfo = value;
                if (selectedUserInfo != null)
                {
                    var group = this.MessageGroups.FirstOrDefault(c => c.UserInfo.Id == value.Id && c.MessageType == Data.MessageType.Text);
                    if (group == null)
                    {
                        group = new MessageGroup() { UserInfo = value, MessageType = Data.MessageType.Text };
                        group.Messages = new ObservableCollection<Data.Message>();
                        MessageGroups.Add(group);
                    }
                    SelectedMessageGroup = group;

                }
                this.NotifyPropertyChanged("SelectedUserInfo");
                //}
            }
        }


        private MessageGroup selectedMessageGroup;
        public MessageGroup SelectedMessageGroup
        {
            get
            {
                return selectedMessageGroup;
            }
            set
            {
                //if (!object.ReferenceEquals(value, selectedMessageGroup))
                //{
                selectedMessageGroup = value;
                if (value != null)
                {
                    foreach (var item in selectedMessageGroup.Messages)
                    {
                        item.IsRead = true;
                    }
                    messageDB.SubmitChanges();
                    G.Navigate.NavigationService.Navigate("/View/Message/ChatPage.xaml?userid=" + value.UserInfo.Id, null);
                }
                this.NotifyPropertyChanged("SelectedMessageGroup");
                //}
            }
        }

        private ObservableCollection<MessageGroup> sessageGroups;
        public ObservableCollection<MessageGroup> MessageGroups
        {
            get
            {
                return sessageGroups;
            }
            set
            {
                if (!object.ReferenceEquals(value, sessageGroups))
                {
                    sessageGroups = value;
                    this.NotifyPropertyChanged("MessageGroups");
                }
            }
        }


        UserInfoService.UserInfoServiceClient userInfoClient = new UserInfoService.UserInfoServiceClient();
        G.Reader.Data.MessageDatabase messageDB = G.Reader.Data.MessageDatabase.Create();
        public MessageViewModel()
        {
            if (instance != null)
                throw new Exception("只能有一个实例");//之所以这么做，是因为需要配合绑定
            instance = this;
            Utils.PushHelp.RecivedRaw += new Utils.ReciveRawHandel(PushHelp_RecivedRaw);
            AddFriendCommand = new Command.CallBackCommand() { CallBack = AddFriend };
            userInfoClient.AddFriendsCompleted += new EventHandler<UserInfoService.AddFriendsCompletedEventArgs>(userInfoClient_AddFriendsCompleted);
            userInfoClient.GetMessagesByReciveUserIdCompleted += new EventHandler<UserInfoService.GetMessagesByReciveUserIdCompletedEventArgs>(userInfoClient_GetMessagesByReciveUserIdCompleted);
        }

        void userInfoClient_AddFriendsCompleted(object sender, UserInfoService.AddFriendsCompletedEventArgs e)
        {
            if (e.Error == null)
            {
                if (e.Result.IsOk)
                {
                    this.Friends.Add(e.friend.FrendUserinfo);
                    G.Navigate.PhoneApplicationPageHelp.ShowState("添加成功");
                }
                else
                {
                    G.Navigate.PhoneApplicationPageHelp.ShowState(e.Result.Message);
                }
            }
        }

        public Command.CallBackCommand AddFriendCommand { get; private set; }

        private void AddFriend(object o)
        {
            UserInfoService.UserInfo user = o as UserInfoService.UserInfo;
            if (user.Id == GloabalData.Instance.User.Id)
            {
                MessageBox.Show("无法添加自己为好友");
                return;
            }
            userInfoClient.AddFriendsAsync(new UserInfoService.Friend() { FriendId = user.Id, HostId = GloabalData.Instance.User.Id });

        }

        private bool isInitial = false;
        public void Initial()
        {
            if (!isInitial)
            {
                userInfoClient.GetFriendsByUserIdCompleted += new EventHandler<UserInfoService.GetFriendsByUserIdCompletedEventArgs>(userInfoClient_GetFriendsByUserIdCompleted);
                userInfoClient.GetFriendsByUserIdAsync(GloabalData.Instance.User.Id);
                var f = (App.Current.RootVisual as Microsoft.Phone.Controls.PhoneApplicationFrame);
                f.Navigated += new System.Windows.Navigation.NavigatedEventHandler(f_Navigated);
                isInitial = true;
            }
        }

        void f_Navigated(object sender, System.Windows.Navigation.NavigationEventArgs e)
        {
            if (e.Uri.OriginalString == "app://external/")
            {
                isNavigatetoExternal = true;
            }
            else
            {
                if (isNavigatetoExternal)
                {
                    userInfoClient.GetMessagesByReciveUserIdAsync(GloabalData.Instance.User.Id);
                    isNavigatetoExternal = false;
                }
            }
        }
        private bool isNavigatetoExternal;


        void PushHelp_RecivedRaw(object obj, Utils.ReciveRawArgs e)
        {
            AddNewMSg(e.Messasge);
            messageDB.SubmitChanges();
        }

        private void AddNewMSg(byte[] msg)
        {
            G.Reader.Data.Message m = new G.Reader.Data.Message();
            m.FromId = BitConverter.ToInt32(msg, 0);
            m.ReciveID = BitConverter.ToInt32(msg, 4);
            m.MessageType = (Data.MessageType)BitConverter.ToInt32(msg, 8);
            m.Body = ReadByteFrom(msg.Length - 12, 12, msg);
            messageDB.MessagesTable.InsertOnSubmit(m);

            var group = this.MessageGroups.FirstOrDefault(c => c.UserInfo.Id == m.FromId && c.MessageType == m.MessageType);
            if (group == null)
            {
                group = new MessageGroup() { UserInfo = this.Friends.FirstOrDefault(c => c.Id == m.FromId) ?? new UserInfoService.UserInfo() { Id = m.FromId, NickName = "匿名" }, MessageType = m.MessageType };
                group.Messages = new ObservableCollection<Data.Message>();
                this.MessageGroups.Add(group);
            }
            Deployment.Current.Dispatcher.BeginInvoke(() =>
            {
                group.Messages.Add(m);
            });
        }
        private byte[] ReadByteFrom(int length, int start, byte[] original)
        {
            byte[] b = new byte[length];
            for (int i = 0; i < length; i++)
            {
                b[i] = original[start + i];
            }
            return b;
        }

        void userInfoClient_GetFriendsByUserIdCompleted(object sender, UserInfoService.GetFriendsByUserIdCompletedEventArgs e)
        {
            this.Friends = e.Result;
            this.MessageGroups = new ObservableCollection<MessageGroup>();
            foreach (var item in messageDB.MessagesTable.Where(c => c.ReciveID == GloabalData.Instance.User.Id && c.IsRead == false))
            {
                var group = this.MessageGroups.FirstOrDefault(c => c.UserInfo.Id == item.FromId && c.MessageType == item.MessageType);
                if (group == null)
                {
                    group = new MessageGroup() { UserInfo = this.Friends.FirstOrDefault(c => c.Id == item.FromId) ?? new UserInfoService.UserInfo() { Id = item.FromId, NickName = "匿名" }, MessageType = item.MessageType };
                    group.Messages = new ObservableCollection<Data.Message>();
                    this.MessageGroups.Add(group);
                }
                group.Messages.Add(item);
            }
            userInfoClient.GetMessagesByReciveUserIdAsync(GloabalData.Instance.User.Id);
        }

        void userInfoClient_GetMessagesByReciveUserIdCompleted(object sender, UserInfoService.GetMessagesByReciveUserIdCompletedEventArgs e)
        {
            if (e.Error == null)
            {
                if (e.Result.Count > 0)
                {
                    foreach (var item in e.Result)
                    {
                        AddNewMSg(item.Msg);
                    }
                    messageDB.SubmitChanges();
                    userInfoClient.RestMessagesStatusAsync(new ObservableCollection<int>(e.Result.Select(c => c.Id)));
                }

                Microsoft.Phone.Shell.StandardTileData std = new Microsoft.Phone.Shell.StandardTileData
                {
                    Count = 0
                };
                var shell = Microsoft.Phone.Shell.ShellTile.ActiveTiles.First();
                shell.Update(std);
            }


        }
    }

    public class MessageGroup : NotifyObject
    {
        //public int FriendID { get; set; }

        //public string FriendName { get; set; }

        public UserInfoService.UserInfo UserInfo { get; set; }

        public G.Reader.Data.MessageType MessageType { get; set; }

        private ObservableCollection<G.Reader.Data.Message> messages;
        public ObservableCollection<G.Reader.Data.Message> Messages
        {
            get
            {
                return messages;
            }
            set
            {
                if (!object.ReferenceEquals(value, messages))
                {
                    messages = value;
                    this.NotifyPropertyChanged("Messages");
                }
            }
        }
    }
}
